const sqlite3 = require('sqlite3').verbose();


const logController = require('../../controller/logController/index')
const UserDB = require('./userDB/index')
const config = require('../../config/index')
const {dtk} = require("../../lib/api/dtkClient");

let {dbFileName, dbFilePath} = config.database
let dbFullPath = dbFilePath + '/' + dbFileName


// 创建数据库连接
let createDB = dbFullPath => new sqlite3.Database(dbFullPath);
let db = createDB(dbFullPath)

class DB {
    /**
     * @desc 表格新建结构修改处理函数的 对象初始化
     * @param mergeTable {Object}  一个包含函数的对象 {a:（）=》{},b:()=>{}}
     */
    #mergeTableHandler = mergeTable => {

        for (let fn of Object.values(mergeTable)) {
            if (Object.prototype.toString.call(fn) !== '[object Function]') continue;
            fn.call(this)
        }
    }

    ClosedTimer = null
    /**
     * @desc 创建表的函数对象 意味着若需要创建新表就向这里更新 但注意修改表结构请使用 this.customSqlExec
     * @type {{createSentenceTable(): void, createUserTable(): void, createKeywordsTable(): void}}
     */
    createTable = {
        createUserTable() {
            let sql = `CREATE TABLE IF NOT EXISTS users
                       (
                           id   INTEGER auto_increment PRIMARY KEY,
                           name TEXT,
                           age  INTEGER
                       )`
            // 创建表格
            this.customSqlExec(sql)
        },

        createKeywordsTable() {
            let sql = `CREATE TABLE IF NOT EXISTS keywords
                       (
                           id   integer auto_increment primary key,
                           word TEXT,
                           time time default current_timestamp
                       )`
            this.customSqlExec(sql)
        },

        /**
         * @desc 这里保存一些小说片段 优美句子
         */
        createSentenceTable() {
            let sql = `CREATE TABLE IF NOT EXISTS sentence
                       (
                           id   integer auto_increment primary key,
                           word TEXT,
                           time time default current_timestamp
                       )`
            this.customSqlExec(sql)
        }
    }
    alterTable = {}


    constructor() {
        if (!this.constructor.initHasExecuted) {
            // 合并执行表格初始化函数
            this.#mergeTableHandler({...this.createTable, ...this.alterTable})
            // 执行事件集中注册函数
            this.addEvents(dbFilePath)
        }
        this.constructor.initHasExecuted = true
        // 实例化userDb
        this.userDB = new UserDB(db)
        // this.autoCRUD = new AutoCRUD(db)
        return db
    }

    /**
     * @desc 注册事件
     */
    addEvents(dbFullPath = '') {
        process.on('beforeExit', () => db.close())
        db.on('open', () => logController.addLog({content: `连接 ${dbFullPath} 成功`}))
        db.on('profile', (sql, time) => logController.addLog({content: `执行语句 ${sql.trim()} 耗时： ${time}`}))
        db.on('change', (type, database, table, rowID) => {
            logController.addLog({
                content: JSON.stringify({type, database, table, rowID})
            })
        })
        db.on('error', err => {
            logController.addLog({content: `db.on('error') ${err.message}`})
        })
        db.on('close', () => logController.addLog({content: dbFullPath + '已关闭'}))
    }

    /**
     *  自定义sql执行
     * @param sql 语句
     * @returns {*}
     */
    customSqlExec(sql) {

        if (sql === undefined || typeof sql !== "string") return void 0
        return new Promise((resolve, reject) =>db.all(sql, (err, rows) => {
            if (err) return reject(err)

            resolve(rows)
        }))

    }

    autoCRUD = {

        /**
         * @desc 断开连接 改用事件记录日志 所以这个处理函数不太需要了
         */
        closeHandler: err => err && logController.addLog({content: db.close + err.message}),
        /**
         *
         * @param tableName
         * @returns {Promise<Object|Error>}
         */
        getTableInfo(tableName) {
            return new Promise((resolve, reject) => {
                db.all(`PRAGMA table_info(${tableName})`, (err, rows) => {
                    if (err) return reject(err)
                    resolve(rows)
                })
            })
        },
        /**
         *
         * @param tableName 哪张表
         * @param where 筛选条件 使用db上的原型函数
         * @param limit 限制条件 使用db上的原型函数
         * @returns {Promise<Array|Error>}
         */
        getRows(tableName, where, limit) {
            let statement = `select *
                             from ${tableName} where ${where} limit ${limit};`
            console.log(statement)
            return new Promise((resolve, reject) => {
                db.all(statement, (err, rows) => {
                    if (err) reject(err)
                    global.rows = rows
                    resolve(rows)
                })
            })
        },
        /**
         * @desc 向某表添加数据
         * @param tableName {String}
         * @param data  {Array[Object]}
         * @return {*|Promise<Error|String>}
         */
        addRows(tableName, data) {
            let keys = []
            if (!data instanceof Array) {
                return void 0
            }
            keys = Object.keys(data[0])
            let statement = ``

            for (let i = 0; i < data.length; i++) {
                let val = Object.values(data[i])
                statement += `insert into ${tableName} (${keys.join(',')})
                              values (`
                let valArr = []
                for (let j = 0; j < val.length; j++) {
                    valArr.push(`"${val[j]}"`)
                }

                statement += valArr.join(',')
                statement += `);`
            }

            return new Promise((resolve, reject) => {
                db.exec(statement, (err) => {
                    if (err) reject(err)
                    resolve('执行成功')
                })
            })
        },
        /**
         * @desc 更新某一行数据
         * @param tableName 表名
         * @param data {Object} rowData
         * @param condition {Array} 例如 [key,value]
         */
        updateRow(tableName, data, condition) {
        },
        delRows(tableName, condition) {
        }
    }
}

/**
 * @desc 构造sql的数量部分 若传一个参数 则认为偏移量为零
 * @param offset
 * @param limit
 */
DB.prototype.limit = (offset, limit) => {
    if (typeof offset !== "number" || typeof limit !== "number") return `limit 0,10`
    if (arguments.length === 1) {
        limit = offset
        return `limit ${limit}`
    }
    return `limit ${offset},${limit}`
}

/**
 * @desc 添加限制条件
 * @param condition 例如 age > 9
 */
DB.prototype.where = (condition) => {
    let str = ` where `
    if (typeof condition !== 'string') return new Error('类型错误 需要传入一个字符串 作为筛选条件')
    return str + condition
}

Array.prototype.equals = function (array) {
    // 长度不相等，直接返回false
    if (this.length !== array.length)
        return false;
    // 遍历数组，检查每个元素是否相等
    for (var i = 0, l = this.length; i < l; i++)
        if (this[i] !== array[i])
            return false;
    return true;
};

// 导出的函数和对象
module.exports = database = new DB()
